<!-- 所有地方都用到 -->
<!DOCTYPE html>
<html lang=en>
<head><meta name="generator" content="Hexo 3.9.0">
    <!-- so meta -->
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="HandheldFriendly" content="True">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta name="description" content="在升级系统架构时，有一个很重要的点容易被研发同学忽略，即只评估了升级的工作量就直接开干。最后到了提测的时候，发现改造范围太大了，测试根本回归不完，升级重构上线遥遥无期。">
<meta property="og:type" content="article">
<meta property="og:title" content="基于流量回放实现读服务的自动化回归测试">
<meta property="og:url" content="http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:description" content="在升级系统架构时，有一个很重要的点容易被研发同学忽略，即只评估了升级的工作量就直接开干。最后到了提测的时候，发现改造范围太大了，测试根本回归不完，升级重构上线遥遥无期。">
<meta property="og:locale" content="en">
<meta property="og:image" content="https://cdn.jsdelivr.net/gh/zhangqinghua/hexo_image/picgo/202204241527777.png">
<meta property="og:image" content="https://cdn.jsdelivr.net/gh/zhangqinghua/hexo_image/picgo/202204241535073.png">
<meta property="og:image" content="https://cdn.jsdelivr.net/gh/zhangqinghua/hexo_image/picgo/202204241556947.png">
<meta property="og:image" content="https://cdn.jsdelivr.net/gh/zhangqinghua/hexo_image/picgo/202204241627600.png">
<meta property="og:image" content="https://cdn.jsdelivr.net/gh/zhangqinghua/hexo_image/picgo/202204241632794.png">
<meta property="og:image" content="https://cdn.jsdelivr.net/gh/zhangqinghua/hexo_image/picgo/202204241648649.png">
<meta property="og:image" content="https://cdn.jsdelivr.net/gh/zhangqinghua/hexo_image/picgo/202204241654102.png">
<meta property="og:image" content="https://cdn.jsdelivr.net/gh/zhangqinghua/hexo_image/picgo/202204241657523.png">
<meta property="og:updated_time" content="2022-04-24T09:05:35.966Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="基于流量回放实现读服务的自动化回归测试">
<meta name="twitter:description" content="在升级系统架构时，有一个很重要的点容易被研发同学忽略，即只评估了升级的工作量就直接开干。最后到了提测的时候，发现改造范围太大了，测试根本回归不完，升级重构上线遥遥无期。">
<meta name="twitter:image" content="https://cdn.jsdelivr.net/gh/zhangqinghua/hexo_image/picgo/202204241527777.png">
    
    
        
          
              <link rel="shortcut icon" href="/images/favicon.ico">
          
        
        
          
            <link rel="icon" type="image/png" href="/images/favicon-192x192.png" sizes="192x192">
          
        
        
          
            <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon.png">
          
        
    
    <!-- title -->
    <title>基于流量回放实现读服务的自动化回归测试</title>
    <!-- styles -->
    <link rel="stylesheet" href="/css/style.css">
    <!-- persian styles -->
    
      <link rel="stylesheet" href="/css/rtl.css">
    
    <!-- rss -->
    
    
</head>

<body class="max-width mx-auto px3 ltr">

    <!-- 导航栏/目录栏 -->
    <!-- 
      <div id="header-post">
  <a id="menu-icon" href="#"><i class="fas fa-bars fa-lg"></i></a>
  <a id="menu-icon-tablet" href="#"><i class="fas fa-bars fa-lg"></i></a>
  <a id="top-icon-tablet" href="#" onclick="$('html, body').animate({ scrollTop: 0 }, 'fast');" style="display:none;"><i class="fas fa-chevron-up fa-lg"></i></a>
  <span id="menu">
    <span id="nav">
      <ul>
         
          <li><a href="/">Home</a></li>
         
          <li><a href="/search/">Search</a></li>
         
          <li><a href="/about/">About</a></li>
        
      </ul>
    </span>
    <br/>
    <span id="actions">
      <ul>
        
        <li><a class="icon" href="/2022/04/18/架构设计/后台架构实战/系统升级，如何实现不停服的数据迁移和用户切换/"><i class="fas fa-chevron-left" aria-hidden="true" onmouseover="$('#i-prev').toggle();" onmouseout="$('#i-prev').toggle();"></i></a></li>
        
        
        <li><a class="icon" href="#" onclick="$('html, body').animate({ scrollTop: 0 }, 'fast');"><i class="fas fa-chevron-up" aria-hidden="true" onmouseover="$('#i-top').toggle();" onmouseout="$('#i-top').toggle();"></i></a></li>
        <li><a class="icon" href="#"><i class="fas fa-share-alt" aria-hidden="true" onmouseover="$('#i-share').toggle();" onmouseout="$('#i-share').toggle();" onclick="$('#share').toggle();return false;"></i></a></li>
      </ul>
      <span id="i-prev" class="info" style="display:none;">Previous post</span>
      <span id="i-next" class="info" style="display:none;">Next post</span>
      <span id="i-top" class="info" style="display:none;">Back to top</span>
      <span id="i-share" class="info" style="display:none;">Share post</span>
    </span>
    <br/>
    <div id="share" style="display: none">
      <ul>
  <li><a class="icon" href="http://www.facebook.com/sharer.php?u=http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/"><i class="fab fa-facebook " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://twitter.com/share?url=http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/&text=基于流量回放实现读服务的自动化回归测试"><i class="fab fa-twitter " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://www.linkedin.com/shareArticle?url=http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/&title=基于流量回放实现读服务的自动化回归测试"><i class="fab fa-linkedin " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://pinterest.com/pin/create/bookmarklet/?url=http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/&is_video=false&description=基于流量回放实现读服务的自动化回归测试"><i class="fab fa-pinterest " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="mailto:?subject=基于流量回放实现读服务的自动化回归测试&body=Check out this article: http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/"><i class="fas fa-envelope " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://getpocket.com/save?url=http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/&title=基于流量回放实现读服务的自动化回归测试"><i class="fab fa-get-pocket " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://reddit.com/submit?url=http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/&title=基于流量回放实现读服务的自动化回归测试"><i class="fab fa-reddit " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://www.stumbleupon.com/submit?url=http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/&title=基于流量回放实现读服务的自动化回归测试"><i class="fab fa-stumbleupon " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://digg.com/submit?url=http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/&title=基于流量回放实现读服务的自动化回归测试"><i class="fab fa-digg " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://www.tumblr.com/share/link?url=http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/&name=基于流量回放实现读服务的自动化回归测试&description=&lt;p&gt;在升级系统架构时，有一个很重要的点容易被研发同学忽略，即只评估了升级的工作量就直接开干。最后到了提测的时候，发现改造范围太大了，测试根本回归不完，升级重构上线遥遥无期。&lt;br&gt;"><i class="fab fa-tumblr " aria-hidden="true"></i></a></li>
</ul>

    </div>
    <div id="toc">
      <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-为什么要自动化"><span class="toc-number">1.</span> <span class="toc-text">1. 为什么要自动化</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-1-针对架构升级的场景"><span class="toc-number">1.0.1.</span> <span class="toc-text">1.1 针对架构升级的场景</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-2-针对日常需求的场景"><span class="toc-number">1.0.2.</span> <span class="toc-text">1.2 针对日常需求的场景</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-如何实现自动化回归"><span class="toc-number">2.</span> <span class="toc-text">2. 如何实现自动化回归</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1-回归自动化前置条件"><span class="toc-number">2.0.1.</span> <span class="toc-text">2.1 回归自动化前置条件</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-2-测试回归整体架"><span class="toc-number">2.0.2.</span> <span class="toc-text">2.2 测试回归整体架</span></a><ol class="toc-child"><li class="toc-item toc-level-6"><a class="toc-link" href="#2-2-1-日志收集"><span class="toc-number">2.0.2.0.1.</span> <span class="toc-text">2.2.1 日志收集</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#2-2-2-数据回放"><span class="toc-number">2.0.2.0.2.</span> <span class="toc-text">2.2.2 数据回放</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#2-2-3-差异对比"><span class="toc-number">2.0.2.0.3.</span> <span class="toc-text">2.2.3 差异对比</span></a></li></ol></li></ol></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-回放的三种模式"><span class="toc-number">3.</span> <span class="toc-text">3. 回放的三种模式</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#3-1-离线回放模式"><span class="toc-number">3.0.1.</span> <span class="toc-text">3.1 离线回放模式</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-2-实时回放模式"><span class="toc-number">3.0.2.</span> <span class="toc-text">3.2 实时回放模式</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-3-无录制的实时回放模式"><span class="toc-number">3.0.3.</span> <span class="toc-text">3.3 无录制的实时回放模式</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-注意事项"><span class="toc-number">4.</span> <span class="toc-text">4. 注意事项</span></a></li></ol>
    </div>
  </span>
</div>

     -->


    <div class="content index py4">
        
        <!-- 文章详情页 -->
<article class="post" itemscope itemtype="http://schema.org/BlogPosting">
  <header>
    
    <h1 class="posttitle" itemprop="name headline">
        基于流量回放实现读服务的自动化回归测试
    </h1>



    <div class="meta">
      <span class="author" itemprop="author" itemscope itemtype="http://schema.org/Person">
        <span itemprop="name">Hexo</span>
      </span>
      <!-- 
2021-11-04
SpringBoot 传参
2021-11-02
Google Analytics Web Gtag 开始
2021-11-02
Google Analytics Web Gtag 衡量常见的用户互动
-->


    <div class="postdate">
      
        <time datetime="2022-04-17T16:00:07.000Z" itemprop="datePublished">2022-04-18</time>
        
        (Updated: <time datetime="2022-04-24T09:05:35.966Z" itemprop="dateModified">2022-04-24</time>)
        
      
    </div>


      <!-- 在文章的头部显示分类 -->


    <div class="article-category">
        <i class="fas fa-archive"></i>
        <a class="category-link" href="/categories/架构设计/">架构设计</a> › <a class="category-link" href="/categories/架构设计/后台架构实战/">后台架构实战</a>
    </div>


      

    </div>
  </header>
  
  <!--不知道是什么
  

  -->

  <div class="content" itemprop="articleBody">
    <p>在升级系统架构时，有一个很重要的点容易被研发同学忽略，即只评估了升级的工作量就直接开干。最后到了提测的时候，发现改造范围太大了，测试根本回归不完，升级重构上线遥遥无期。<br><a id="more"></a></p>
<p>随着业务的发展，系统相应的进行升级重构是不可避免的，但与此同时也带来了巨大的测试回归量。本章节介绍了一种自动化的测试回归架构方案，它能够极大的降低读业务因升级重构而带来的回归问题，同时还能适配日常需求上线的回归工作量，真正做到了回归自动化，研发自主化，避免用户场景覆盖遗漏导致的漏测问题。</p>
<h2 id="1-为什么要自动化"><a href="#1-为什么要自动化" class="headerlink" title="1. 为什么要自动化"></a>1. 为什么要自动化</h2><h4 id="1-1-针对架构升级的场景"><a href="#1-1-针对架构升级的场景" class="headerlink" title="1.1 针对架构升级的场景"></a>1.1 针对架构升级的场景</h4><p>首先我们来看针对架构升级的场景，不管是因为技术还是业务导致的系统重构架构升级，它的改造量和范围都是非常大的。对于此类系统级的重构，测试回归的工作量至少都是以月为单位，对于人力的消耗巨大。</p>
<p>一种应对方案是先不改造，到系统实在扛不住了，再想办法。另一种应对方案是先暂停需求，全力进行改造。</p>
<p>但在实际工作场景中，上述应对策略往往很难实现。</p>
<h4 id="1-2-针对日常需求的场景"><a href="#1-2-针对日常需求的场景" class="headerlink" title="1.2 针对日常需求的场景"></a>1.2 针对日常需求的场景</h4><p>再来看看针对日常需求的场景，对于后台系统基本上都是微服务架构，对外会提供一至多个接口，一般一个需求只会涉及一个或者几个接口的某些场景的修改，测试同学也只会对改造的接口及对应的场景进行测试。</p>
<p>但在实际案例里，需求涉及的接口或场景上线后均不会出现 Bug，但同一个服务里的其他接口，即<strong>当次未涉及修改的被测接口</strong>，就比较容易出现 Bug。因为虽然对外接口是不同的，但是底层逻辑很可能是复用了相同代码，这导致了相互影响。</p>
<p>为了避免此情景，对于任何一个需求，测试人员都需要回归所有接口，这个工作量是巨大的。</p>
<p>针对上述问题，通过自动化的方式提升效率，便是我们的不二选择。</p>
<h2 id="2-如何实现自动化回归"><a href="#2-如何实现自动化回归" class="headerlink" title="2. 如何实现自动化回归"></a>2. 如何实现自动化回归</h2><h4 id="2-1-回归自动化前置条件"><a href="#2-1-回归自动化前置条件" class="headerlink" title="2.1 回归自动化前置条件"></a>2.1 回归自动化前置条件</h4><p>首先我们来看一下自动化回归方案的基本原理，读服务能够实现测试回归自动化有两个前置条件：</p>
<ol>
<li><p>读服务均是查询，无状态的<br> 无状态是指每次请求都是<strong>无副作用</strong>的、<strong>可以重复</strong>的，同样的请求入参，在后台数据无变化的情况下，多次重试的结果均一样。</p>
<p> 相比而言，写或者扣减业务就不行，比如用户的余额变化就会产生副作用。具体来说上一次购物订单支付成功，第二次和上一次使用同样的金额进行支付，就不一定能成功。因为上一次的支付产生了副作用，用户的余额减少了，导致此次支付不成功。</p>
</li>
<li><p>读服务对外接口的出入参格式没有发生变化<br> 不管服务内部的逻辑如何变化，只要接口出入参格式不变，就可以利用读服务的无状态特性进行流量回放。</p>
</li>
</ol>
<p><img src="https://cdn.jsdelivr.net/gh/zhangqinghua/hexo_image/picgo/202204241527777.png" alt=""></p>
<h4 id="2-2-测试回归整体架"><a href="#2-2-测试回归整体架" class="headerlink" title="2.2 测试回归整体架"></a>2.2 测试回归整体架</h4><p>下图展示的是读服务的自动化测试回归整体架构图。在这个架构里包含三大模块，分别为日志收集、数据回放以及差异对比：</p>
<ul>
<li><p>日志收集的主要作用是收集被测系统的真实用户请求，基于一定规则处理后作为系统用例；</p>
</li>
<li><p>数据回放是基于收集的用例对被测系统进行数据回放，发起自动化测试回归；</p>
</li>
<li><p>差异对比类似人工测试发现 Bug 的过程，通过差异对比自动发现与预期不一致的用例，进而确定 Bug。</p>
</li>
</ul>
<p><img src="https://cdn.jsdelivr.net/gh/zhangqinghua/hexo_image/picgo/202204241535073.png" alt=""></p>
<h6 id="2-2-1-日志收集"><a href="#2-2-1-日志收集" class="headerlink" title="2.2.1 日志收集"></a>2.2.1 日志收集</h6><p>不管是接口是 HTTP 形式还是 RPC 形式的后台读服务，都可以通过现在比较成熟的过滤器进行日志收集，比如 Spring 的 <code>Intercept</code>、Servlet 的 <code>Filter</code> 等，采用过滤器的架构如下图所示。</p>
<p><img src="https://cdn.jsdelivr.net/gh/zhangqinghua/hexo_image/picgo/202204241556947.png" alt=""></p>
<p>在过滤器中会对所有请求的入参和出参进行记录，并通过 MQ 发送出去。记录的数据格式大致如下：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;<span class="attr">"应用名"</span>: <span class="string">"XXX"</span>, <span class="attr">"接口方法名"</span>: <span class="string">"RCP 记录接口方法名称，HTTP 记录域名及路径"</span>, <span class="attr">"入参数"</span>: <span class="string">"xxx"</span>, <span class="attr">"出参"</span>: <span class="string">""</span>&#125;</span><br></pre></td></tr></table></figure>
<p>对于发送出去的 MQ，自动化回归的消费服务，会按应用和接口进行处理。对于应用和接口方法的标识数据可以存储在数据库里，对于入参和出参可以存储在 NoSQL 里，比如 HBase。</p>
<p>之所以将出入参数数据存储在 HBase 里，是因为入参和出参数据量较大，存储在数据库里查询性能会比较差，即使将参数存储在原生支持分布式的 NoSQL 里，也要对采集的日志进行一些过滤、去重以及无效数据定期清理等操作。</p>
<p>此外对于压测等非业务场景需要关闭日志采集，毕竟日常业务请求带来的数据量可能一天都上亿或十几亿次，如果不做管控，对于存储的消耗将是巨大的。</p>
<p>当前日志收集采用的过滤器是和业务应用同属于一个进程，它会占用业务应用类的内存资源，同时对于业务也存在一定的侵入性。当遇到此种情况，可以将日志收集独立出来，采用单独进程进行收集。</p>
<p><img src="https://cdn.jsdelivr.net/gh/zhangqinghua/hexo_image/picgo/202204241627600.png" alt=""></p>
<p>采用单独进程后，业务应用需要按上述格式将出入参与日志打印到指定文件，单独的数据收集进程，只需要对此文件进行监控，并将变化发送至 MQ 集合。</p>
<p>在操作系统里可以单独对进行设计资源占用的限制。为了保证业务应用不被日采集所影响，可以对采集进程设置内存 CPU 等限制，并配置资源占有报警。</p>
<h6 id="2-2-2-数据回放"><a href="#2-2-2-数据回放" class="headerlink" title="2.2.2 数据回放"></a>2.2.2 数据回放</h6><p>有了上面的出入参之后，便可以在测试时进行回放了。数据回放主要的作用是基于日志里记录的接口信息和入参，去实时调用被测系统，并存储实时回放返回的出参信息。</p>
<p><img src="https://cdn.jsdelivr.net/gh/zhangqinghua/hexo_image/picgo/202204241632794.png" alt=""></p>
<p>实时回放时，如果是 HTTP 形式的接口，采用主流的 HTTP 客户端即可。如果是 RPC 形式接口，需要使用该 RPC 框架提供的能够调用任意被测接口的客户端。</p>
<h6 id="2-2-3-差异对比"><a href="#2-2-3-差异对比" class="headerlink" title="2.2.3 差异对比"></a>2.2.3 差异对比</h6><p>在完成了数据回放后，便可以对回放产生的结果数据与预期数据，比如收集这里的出差进行比较。数据对比有很多形式，比如基于二进制的校验和基于文本的校验。</p>
<p>二进制的校验方式只是告诉你数据是否整体一致，而不会展示具体哪里不一致，即使展示了，但因为是二进制，人工也无法查看。</p>
<p>文本的校验方式是先将数据转换为 JSON 格式再进行对比，使用文本格式可以看到数据整体不一致，以及具体是何处导致的不一致。</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;"name": "一本书", "sku": 123&#125; // 预期数据</span><br><span class="line"></span><br><span class="line">&#123;"name": "一书本", "sku": 123&#125; // 结果数据</span><br></pre></td></tr></table></figure>
<p>从上面可以看到同一个 SKU 的名称在两边出现的不一致。如果只是进行了系统的重构，相同的 SKU 对应的数据应该是一样，此处出现了不一致代表出现了bug。</p>
<p>采用文本对比，可以直观的看到哪个自传数据有差异，从而更快定位到问题。</p>
<p>正常情况下，只要<strong>存在差异的数据</strong>，均可认为是 Bug，是需要进行修复的。但有些时候比如接口会对每次请求产生一个唯一标识，用此标识来打印日志并返回给调用方。在差异对比时，此类接口每次都会因为唯一标识不同，而导致对比出现差异，但此差异又不会对业务产生影响。对于此类场景需要差异对比工具具备忽略功能，在对比时忽略唯一标识字段。</p>
<p>通过数据收集回放和差异对比，能够实现自动化可视化，将读业务的测试回归完全自动化。</p>
<h2 id="3-回放的三种模式"><a href="#3-回放的三种模式" class="headerlink" title="3. 回放的三种模式"></a>3. 回放的三种模式</h2><p>上述讲解的自动化测试的整体流程和实现步骤，关于回放，我们只讲解了技术实现，接下来我再介绍几种需要你重点关注的模式。</p>
<h4 id="3-1-离线回放模式"><a href="#3-1-离线回放模式" class="headerlink" title="3.1 离线回放模式"></a>3.1 离线回放模式</h4><p>离线回报模式是指在回放时只调用进行改造的新服务，将新服返回的数据与收集日志的出参进行比较。</p>
<p><img src="https://cdn.jsdelivr.net/gh/zhangqinghua/hexo_image/picgo/202204241648649.png" alt=""></p>
<p>采用离线回放的好处是减少了对于线上老版本的调用量，避免对线上产生影响，也节约了资源。但存在一个问题，如果后台存储中的数据已经发生了变化，此时就不能使用收集的日子里的出参，因为从新版本实时查看出的数据，与历史收集的日志数据已经不准了。</p>
<h4 id="3-2-实时回放模式"><a href="#3-2-实时回放模式" class="headerlink" title="3.2 实时回放模式"></a>3.2 实时回放模式</h4><p>为了解决离线回放模式里因为数据变化导致的收集日志的出参无效问题，可以采用实时回放的模式，在收集的日志里只记录入参而不记录出参。研发或测试手动触发回放功能后，使用入参实时的调用新老版本的被测应用，并对比双方返回的出参，通过此方式可以规避数据变更的问题。</p>
<p><img src="https://cdn.jsdelivr.net/gh/zhangqinghua/hexo_image/picgo/202204241654102.png" alt=""></p>
<h4 id="3-3-无录制的实时回放模式"><a href="#3-3-无录制的实时回放模式" class="headerlink" title="3.3 无录制的实时回放模式"></a>3.3 无录制的实时回放模式</h4><p>不管是离线回放还是实时回放都存在一个问题，我们是对接口的入参进行录制再回放的，因存储容量有限，只能存储一定数量的数据，很多日志用例可能会被丢弃，这就可能导致有些重要场景会被漏测。</p>
<p>针对这个问题，可以采用无录制的实时回放模式。无录制实时回放不再记录入参数据，当日志消费模块接收到收集的日志用例后，实时调用新老版本被测服务，并进行数据对比。</p>
<p><img src="https://cdn.jsdelivr.net/gh/zhangqinghua/hexo_image/picgo/202204241657523.png" alt=""></p>
<p>使用此方式进行几周或者更久的回放，基本能够覆盖全部场景。</p>
<h2 id="4-注意事项"><a href="#4-注意事项" class="headerlink" title="4. 注意事项"></a>4. 注意事项</h2><p>在线上部署及使用自动化回归工具时，也有一些需要注意与规避的点。</p>
<p>第一个需要注意的点是，在进行自动化回归时，写接口一定要屏蔽。以用户注册为例，如果在回放时没有屏蔽，使用线上入参进行回放，将会产生很多垃圾用户给后续的业务流程带来巨大影响。</p>
<p>第二个需要注意的点是，上述回放模式里除了离线模式外，实时回放模式和无录制的实时回放模式都会对线上系统产生一定的流量压力。假设被测系统的性能比较差，或者机械数较少，自动化回放的流量会把线上系统打挂，进而影响业务不可用。特别无录制的实时回报模式，带来的流量更大，且持续时间更长。</p>
<p>第二个需要注意的点是，即使采用了无录制的实时回报模式，也只是通过更长时间的回放，尽可能的覆盖更多的业务场景，但也并没有足够的证据表明一定不会出现漏测。对于此种问题，可以借助一些代码覆盖率的工具，如 Java 里的 Jacoco 来统计一些回放后被测系统的代码覆盖率，通过数据来判断是否存在可能的漏测。</p>
<p>我们讲介绍了读业务在系统重构及日常需求开发时，均存在的测试回归耗时长和可能存在漏测的问题。根据读业务无状态及可重复执行的特点，针对上述问题，我们构建了一套基于业务日志的自动化合规平台，主要包含三大子模块，分别是日志采集、数据回放及差异对比。</p>

  </div>
</article>


<!--  -->


        
          <div id="footer-post-container">
  <div id="footer-post">

    <div id="nav-footer" style="display: none">
      <ul>
         
          <li><a href="/">Home</a></li>
         
          <li><a href="/search/">Search</a></li>
         
          <li><a href="/about/">About</a></li>
        
      </ul>
    </div>

    <div id="toc-footer" style="display: none">
      <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-为什么要自动化"><span class="toc-number">1.</span> <span class="toc-text">1. 为什么要自动化</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-1-针对架构升级的场景"><span class="toc-number">1.0.1.</span> <span class="toc-text">1.1 针对架构升级的场景</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-2-针对日常需求的场景"><span class="toc-number">1.0.2.</span> <span class="toc-text">1.2 针对日常需求的场景</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-如何实现自动化回归"><span class="toc-number">2.</span> <span class="toc-text">2. 如何实现自动化回归</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1-回归自动化前置条件"><span class="toc-number">2.0.1.</span> <span class="toc-text">2.1 回归自动化前置条件</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-2-测试回归整体架"><span class="toc-number">2.0.2.</span> <span class="toc-text">2.2 测试回归整体架</span></a><ol class="toc-child"><li class="toc-item toc-level-6"><a class="toc-link" href="#2-2-1-日志收集"><span class="toc-number">2.0.2.0.1.</span> <span class="toc-text">2.2.1 日志收集</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#2-2-2-数据回放"><span class="toc-number">2.0.2.0.2.</span> <span class="toc-text">2.2.2 数据回放</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#2-2-3-差异对比"><span class="toc-number">2.0.2.0.3.</span> <span class="toc-text">2.2.3 差异对比</span></a></li></ol></li></ol></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-回放的三种模式"><span class="toc-number">3.</span> <span class="toc-text">3. 回放的三种模式</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#3-1-离线回放模式"><span class="toc-number">3.0.1.</span> <span class="toc-text">3.1 离线回放模式</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-2-实时回放模式"><span class="toc-number">3.0.2.</span> <span class="toc-text">3.2 实时回放模式</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-3-无录制的实时回放模式"><span class="toc-number">3.0.3.</span> <span class="toc-text">3.3 无录制的实时回放模式</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-注意事项"><span class="toc-number">4.</span> <span class="toc-text">4. 注意事项</span></a></li></ol>
    </div>

    <div id="share-footer" style="display: none">
      <ul>
  <li><a class="icon" href="http://www.facebook.com/sharer.php?u=http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/"><i class="fab fa-facebook fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://twitter.com/share?url=http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/&text=基于流量回放实现读服务的自动化回归测试"><i class="fab fa-twitter fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://www.linkedin.com/shareArticle?url=http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/&title=基于流量回放实现读服务的自动化回归测试"><i class="fab fa-linkedin fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://pinterest.com/pin/create/bookmarklet/?url=http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/&is_video=false&description=基于流量回放实现读服务的自动化回归测试"><i class="fab fa-pinterest fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="mailto:?subject=基于流量回放实现读服务的自动化回归测试&body=Check out this article: http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/"><i class="fas fa-envelope fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://getpocket.com/save?url=http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/&title=基于流量回放实现读服务的自动化回归测试"><i class="fab fa-get-pocket fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://reddit.com/submit?url=http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/&title=基于流量回放实现读服务的自动化回归测试"><i class="fab fa-reddit fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://www.stumbleupon.com/submit?url=http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/&title=基于流量回放实现读服务的自动化回归测试"><i class="fab fa-stumbleupon fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://digg.com/submit?url=http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/&title=基于流量回放实现读服务的自动化回归测试"><i class="fab fa-digg fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://www.tumblr.com/share/link?url=http://yoursite.com/2022/04/18/架构设计/后台架构实战/基于流量回放实现读服务的自动化回归测试/&name=基于流量回放实现读服务的自动化回归测试&description=&lt;p&gt;在升级系统架构时，有一个很重要的点容易被研发同学忽略，即只评估了升级的工作量就直接开干。最后到了提测的时候，发现改造范围太大了，测试根本回归不完，升级重构上线遥遥无期。&lt;br&gt;"><i class="fab fa-tumblr fa-lg" aria-hidden="true"></i></a></li>
</ul>

    </div>

<!-- 先隐藏底部框 -->
    <!-- <div id="actions-footer">
        <a id="menu" class="icon" href="#" onclick="$('#nav-footer').toggle();return false;"><i class="fas fa-bars fa-lg" aria-hidden="true"></i> Menu</a>
        <a id="toc" class="icon" href="#" onclick="$('#toc-footer').toggle();return false;"><i class="fas fa-list fa-lg" aria-hidden="true"></i> TOC</a>
        <a id="share" class="icon" href="#" onclick="$('#share-footer').toggle();return false;"><i class="fas fa-share-alt fa-lg" aria-hidden="true"></i> Share</a>
        <a id="top" style="display:none" class="icon" href="#" onclick="$('html, body').animate({ scrollTop: 0 }, 'fast');"><i class="fas fa-chevron-up fa-lg" aria-hidden="true"></i> Top</a>
    </div> -->

  </div>
</div>

        
        <!-- <footer id="footer">
  <div class="footer-left">
    Copyright &copy; 2022 John Doe
  </div>
  <div class="footer-right">
    <nav>
      <ul>
        
        <li><a href="/">Home</a></li>
        
        <li><a href="/search/">Search</a></li>
        
        <li><a href="/about/">About</a></li>
        
      </ul>
    </nav>
  </div>
</footer> -->



<!-- 根据页面mathjax变量决定是否加载MathJax数学公式js -->

    </div>
    <!-- styles -->
<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">
<link rel="stylesheet" href="/lib/justified-gallery/css/justifiedGallery.min.css">

    <!-- jquery -->
<script src="/lib/jquery/jquery.min.js"></script>
<script src="/lib/justified-gallery/js/jquery.justifiedGallery.min.js"></script>
<!-- clipboard -->

  <script src="/lib/clipboard/clipboard.min.js"></script>
  <script type="text/javascript">
  $(function() {
    // copy-btn HTML
    var btn = "<span class=\"btn-copy tooltipped tooltipped-sw\" aria-label=\"Copy to clipboard!\">";
    btn += '<i class="far fa-clone"></i>';
    btn += '</span>'; 
    // mount it!
    $(".highlight .code pre").before(btn);
    var clip = new ClipboardJS('.btn-copy', {
      target: function(trigger) {
        return trigger.nextElementSibling;
      }
    });
    clip.on('success', function(e) {
      e.trigger.setAttribute('aria-label', "Copied!");
      e.clearSelection();
    })
  })
  </script>

<script src="/js/main.js"></script>
<!-- search -->

<!-- Google Analytics -->

<!-- Baidu Analytics -->

<!-- Disqus Comments -->


</body>
</html>
